package productAndConsumer;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/*
    生产者与消费者：
        1个线程对number做+1操作，1个线程对number做-1操作，循环10次
    多线程的判断应该用while循环判断来避免线程的虚假唤醒
    旧版本  锁: synchronized  等待: wait()  唤醒: notifyAll()/notify()
    新版本  锁: Lock          等待: await() 唤醒: signalAll()/signal()
 */
public class ProductAndConsumer {
    public static void main(String[] args) {
        Number number=new Number();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                number.increment();
            }
        },"A").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                number.reduce();
            }
        },"B").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                number.increment();
            }
        },"C").start();
        new Thread(()->{
            for (int i = 0; i < 10; i++) {
                number.reduce();
            }
        },"D").start();
    }
}
class Number{
    private int number;
    private Lock lock=new ReentrantLock();
    private Condition condition=lock.newCondition();

    public void increment(){
        lock.lock();
        try {
            while (number!=0){
                condition.await();
            }
            number++;
            System.out.println(Thread.currentThread().getName()+":"+number);
            condition.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }

    }

    public void reduce(){
        lock.lock();
        try {
            while (number==0){
                try {
                    condition.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            number--;
            System.out.println(Thread.currentThread().getName()+":"+number);
            condition.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }

    }

//    public synchronized void increment(){
//        while (number!=0){
//            try {
//                this.wait();
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//        }
//        number++;
//        System.out.println(Thread.currentThread().getName()+":"+number);
//        this.notifyAll();
//    }
//
//    public synchronized void reduce(){
//        while (number==0){
//            try {
//                this.wait();
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//        }
//        number--;
//        System.out.println(Thread.currentThread().getName()+":"+number);
//        this.notifyAll();
//    }
}
